from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel

from commons.database import Database
from DAL.category import Category

router = APIRouter(prefix='/api/categories', tags=['categories'])


class CategoryCreate(BaseModel):
    """创建分类请求模型"""
    name: str
    parent_id: Optional[int] = None
    description: Optional[str] = None


class CategoryUpdate(BaseModel):
    """更新分类请求模型"""
    name: Optional[str] = None
    parent_id: Optional[int] = None
    description: Optional[str] = None


class CategoryResponse(BaseModel):
    """分类响应模型"""
    id: int
    name: str
    parent_id: Optional[int]
    description: Optional[str]
    created_at: str
    updated_at: str
    children: Optional[List['CategoryResponse']] = None

    class Config:
        from_attributes = True

# 解决自引用模型的导入问题
CategoryResponse.update_forward_refs()


def get_db():
    """获取数据库会话"""
    db = next(Database.get_db())
    try:
        yield db
    finally:
        db.close()


@router.post('', response_model=CategoryResponse)
async def create_category(category: CategoryCreate, db: Session = Depends(get_db)):
    """
    创建新的商品分类
    :param category: 分类信息
    :param db: 数据库会话
    :return: 创建的分类信息
    """
    # 检查父分类是否存在
    if category.parent_id:
        parent = db.query(Category).filter(Category.id == category.parent_id).first()
        if not parent:
            raise HTTPException(status_code=404, detail=f"父分类ID {category.parent_id} 不存在")

    # 创建新分类
    db_category = Category(
        name=category.name,
        parent_id=category.parent_id,
        description=category.description
    )
    db.add(db_category)
    db.commit()
    db.refresh(db_category)
    return db_category.to_dict(include_children=False)


@router.get('', response_model=List[CategoryResponse])
async def get_categories(
    parent_id: Optional[int] = None,
    include_children: bool = False,
    db: Session = Depends(get_db)
):
    """
    获取分类列表，支持按父分类ID筛选和级联查询子分类
    :param parent_id: 父分类ID，为None时返回所有顶级分类
    :param include_children: 是否包含子分类
    :param db: 数据库会话
    :return: 分类列表
    """
    query = db.query(Category)
    if parent_id is not None:
        query = query.filter(Category.parent_id == parent_id)
    else:
        # 默认返回顶级分类
        query = query.filter(Category.parent_id.is_(None))

    categories = query.all()
    return [category.to_dict(include_children=include_children) for category in categories]


@router.get('/{category_id}', response_model=CategoryResponse)
async def get_category(category_id: int, include_children: bool = True, db: Session = Depends(get_db)):
    """
    获取单个分类详情，支持级联查询子分类
    :param category_id: 分类ID
    :param include_children: 是否包含子分类
    :param db: 数据库会话
    :return: 分类详情
    """
    category = db.query(Category).filter(Category.id == category_id).first()
    if not category:
        raise HTTPException(status_code=404, detail=f"分类ID {category_id} 不存在")
    return category.to_dict(include_children=include_children)


@router.put('/{category_id}', response_model=CategoryResponse)
async def update_category(
    category_id: int,
    category_update: CategoryUpdate,
    db: Session = Depends(get_db)
):
    """
    更新分类信息
    :param category_id: 分类ID
    :param category_update: 更新的分类信息
    :param db: 数据库会话
    :return: 更新后的分类信息
    """
    db_category = db.query(Category).filter(Category.id == category_id).first()
    if not db_category:
        raise HTTPException(status_code=404, detail=f"分类ID {category_id} 不存在")

    # 检查父分类是否存在（如果提供）
    if category_update.parent_id is not None:
        # 防止自引用
        if category_update.parent_id == category_id:
            raise HTTPException(status_code=400, detail="分类不能将自己设置为父分类")

        parent = db.query(Category).filter(Category.id == category_update.parent_id).first()
        if not parent:
            raise HTTPException(status_code=404, detail=f"父分类ID {category_update.parent_id} 不存在")

    # 更新分类信息
    update_data = category_update.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_category, key, value)

    db.commit()
    db.refresh(db_category)
    return db_category.to_dict(include_children=False)


@router.delete('/{category_id}', response_model=dict)
async def delete_category(category_id: int, db: Session = Depends(get_db)):
    """
    删除分类
    :param category_id: 分类ID
    :param db: 数据库会话
    :return: 删除结果
    """
    category = db.query(Category).filter(Category.id == category_id).first()
    if not category:
        raise HTTPException(status_code=404, detail=f"分类ID {category_id} 不存在")

    # 检查是否有子分类
    children = db.query(Category).filter(Category.parent_id == category_id).first()
    if children:
        raise HTTPException(status_code=400, detail=f"分类ID {category_id} 存在子分类，请先删除子分类")

    db.delete(category)
    db.commit()
    return {"message": f"分类ID {category_id} 已成功删除"}